package parser;

import antlr.RecognitionException;
import antlr.Token;
import java.util.*;

class Call extends Expr {
    
    Expr left;
    Parameters args;
    
    Call(Expr left,  Parameters args) {
        this.left = left;
        this.args = args;
    }
    
    void delete(ByteStream out) throws RecognitionException {
        throw new RecognitionException("Cannot delete rvalue");
    }

    static void writeParameters(Parameters p, ByteStream out) throws RecognitionException {
        boolean tuple_dict = (p.tuple != null || p.dict != null ||
                              p.keywords.size() != 0);
        if (tuple_dict) {
            if (p.positional.size() == 0) {
                if (p.tuple == null) {
                    out.write(Opcodes.EMPTY_TUPLE);
                } else {
                    p.tuple.tuple_parameter(out);
                }
            } else {
                for (Expr e : p.positional) {
                    e.write(out);
                }
                out.write(Opcodes.PACK);
                out.write(p.positional.size());
                if (p.tuple != null) {
                    p.tuple.write(out);
                    out.write(Opcodes.TUPLE_CONCAT);
                }
            }
            if (p.dict != null) {
                p.dict.write(out);
                out.write(Opcodes.COPY_DICT);
            } else {
                out.write(Opcodes.DICTIONARY);
            }
            for (int i = 0; i < p.keywords.size(); i+=2) { 
                Expr k = p.keywords.get(i);
                Expr v = p.keywords.get(i+1);
                k.write(out);
                v.write(out);
                out.write(Opcodes.DICT_INSERT);
            }
        } else {
            for (Expr e : p.positional) {
                e.write(out);
            }
            out.write(Opcodes.PACK_PARAMS);
            out.write(p.positional.size());
        }
    }    
  
    void write(ByteStream out) throws RecognitionException {
        left.write(out);
        writeParameters(args, out);
        out.write(Opcodes.F_CALL);
    }
    
    void writeLHS(ByteStream out) throws RecognitionException {
        throw new RecognitionException("Cannot assign to function call");
    }
    
    static final int KEYWORDS_INDEX = 1;
    static final int TUPLE_INDEX = 2;
    static final int DICT_INDEX = 4;
        
}
